import 'package:flutter/material.dart';

abstract class IndexModel {
  bool isIndex(); // 主 list 显示索引行
  String getIndex(); // 获取索引字符
}

class FriendIndexModel extends IndexModel {
  final String friendName;
  final String url;
  final String index;

  FriendIndexModel({
    this.friendName,
    this.url,
    this.index,
  });

  @override
  String getIndex() {
    return this.index;
  }

  @override
  bool isIndex() {
    return index != null;
  }
}

typedef Widget ModelHandler(IndexModel modelData);
typedef Widget IndexHandler(String modelIndex);
typedef Widget ShowIndexHandler(String index);

class IndexListView extends StatefulWidget {
  final List<IndexModel> modelList; // 主数据 (其中要包含索引数据) 如：A, 阿三, 阿Q, B, 奔三
  final List<String> indexList; // 右侧索引数据 A,B,C,D ...

  final ModelHandler modelHandler; // 渲染主数据(不含索引数据)函数
  final IndexHandler indexHandler; // 渲染主数据中的索引数据 函数

  final ShowIndexHandler showIndexHandler; // 右侧索引被点击时，屏幕中间会渲染索引的 处理函数

  final double modelWidgetHeight; // 主数据的 高度

  final double indexWidgetHeight; // 主数据中索引数据的 高度

  const IndexListView({
    @required this.modelList,
    @required this.indexList,
    @required this.modelHandler,
    @required this.indexHandler,
    @required this.showIndexHandler,
    @required this.modelWidgetHeight,
    @required this.indexWidgetHeight,
  });

  @override
  _IndexListViewState createState() => _IndexListViewState();
}

class _IndexListViewState extends State<IndexListView> {
  final List<GlobalKey> _keys = [];
  bool _flag = false;
  String _value = "";
  ScrollController _controller = ScrollController();

  @override
  Widget build(BuildContext context) {
    return Stack(
      alignment: Alignment.topRight,
      children: <Widget>[
        _buildData(widget.modelList, widget.modelHandler, widget.indexHandler),
        _rightIndexWidgets(widget.indexList),
        _showIndexWidgets(),
      ],
    );
  }

  Widget _rightIndexWidgets(List<String> indexList) {
    setState(() {
      _keys.clear();
    });
    var _listWidget = indexList.map((i) {
      GlobalKey _key = GlobalKey();
      setState(() {
        _keys.add(_key);
      });
      return Container(
        key: _key,
        alignment: Alignment.center,
        width: 30.0,
        child: Text(
          i,
          style: TextStyle(fontSize: 16.0),
          textAlign: TextAlign.end,
        ),
      );
    }).toList();

    return GestureDetector(
        behavior: HitTestBehavior.opaque,
        child: Container(
            color: _flag ? Colors.grey[300] : null,
            child: Column(
              mainAxisSize: MainAxisSize.max,
              mainAxisAlignment: MainAxisAlignment.center,
              children: _listWidget,
            )),
        onTapDown: (point) {
          // print("手指接触屏幕 point: ${point.globalPosition}");
          // print("point: ${point.globalPosition.dy}");
          setState(() {
            _flag = !_flag;
          });
          _changeShowIndex(point.globalPosition.dy);
        },
        onTapUp: (point) {
          // print("手指离开屏幕");
          setState(() {
            _flag = false;
          });
          _changeShowIndex(point.globalPosition.dy);
        },
        onVerticalDragStart: (point) {
          // print("开始移动 point: $point");
          _changeShowIndex(point.globalPosition.dy);
        },
        onVerticalDragUpdate: (point) {
          // print("移动 ... => ${point.globalPosition.dy}");
          _changeShowIndex(point.globalPosition.dy);
        },
        onVerticalDragDown: (point) {
          // print("开始垂直移动 point: $point");
          _changeShowIndex(point.globalPosition.dy);
        },
        onVerticalDragEnd: (point) {
          // print("当用户停止移动时 point: $point");
          setState(() {
            _flag = !_flag;
          });
        });
  }

  void _changeShowIndex(double dy) {
    int _index = _getIndexByPositions(dy);
    var _value0 = widget.indexList[_index];

    setState(() {
      _value = _value0;
    });

    int _itemIndexNum = 0;
    int _dataIndex = widget.modelList.indexWhere((t) {
      if(t.isIndex()) {
        _itemIndexNum = _itemIndexNum + 1;
      }
      return t.getIndex() == _value0;
    } );
    // 筛选出 有几个 索引 Item ```` a, a0, a1, a2, a3, a4, a5, b
    if (_dataIndex >= 0) {
      _itemIndexNum = _itemIndexNum - 1;
      _controller.animateTo(((_dataIndex - _itemIndexNum) * (widget.modelWidgetHeight)
       + (_itemIndexNum * widget.indexWidgetHeight)),
          duration: Duration(milliseconds: 500), curve: Curves.ease);
    }
  }

  int _getIndexByPositions(double position1) {
    var _values = <SortValue>[];

    for (int i = 0; i < _keys.length; i++) {
      final BuildContext context = _keys[i].currentContext;

      final RenderBox renderBox = context.findRenderObject();
      final position = renderBox.localToGlobal(Offset.zero);
      SortValue _sortValue = SortValue(position.dy - position1, i);
      _values.add(_sortValue);
    }

    _values = _values.map((i) {
      if (i.offset < 0) {
        i.offset = i.offset.abs();
      }
      return i;
    }).toList();
    _values.sort((v1, v2) => (v1.offset - v2.offset).floor());
    return _values.first.index;
  }

  Widget _showIndexWidgets() {
    return Offstage(
      child: widget.showIndexHandler(_value),
      offstage: !_flag,
    );
  }
  
  Widget _buildData(List<IndexModel> modelList, ModelHandler modelHandler, IndexHandler indexHandler) {
  return ListView.builder(
    controller: _controller,
    itemCount: modelList.length,
    itemBuilder: (context, index) {
      var model = modelList[index];
      return model.isIndex() ? indexHandler(model.getIndex()) : modelHandler(model);
    },
  );
}

}


class SortValue {
  double offset;

  final int index;

  SortValue(this.offset, this.index);

  @override
  String toString() {
    return """
      SortValue: offset=$offset, index=$index
      """;
  }
}
